1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 package sun.tools.jconsole;
27
28 import java.awt.*;
29 import java.awt.event.*;
30 import java.io.*;
31 import java.lang.management.*;
32 import java.lang.reflect.*;
33 import java.util.*;
34 import java.util.concurrent.*;
35
36 import javax.accessibility.*;
37 import javax.management.*;
38 import javax.management.openmbean.CompositeData;
39 import javax.swing.*;
40 import javax.swing.border.*;
41 import javax.swing.text.*;
42
43 import sun.management.*;
44
45 import static sun.tools.jconsole.Formatter.*;
46 import static sun.tools.jconsole.OverviewPanel.*;
47 import static sun.tools.jconsole.Resources.*;
48 import static sun.tools.jconsole.Utilities.*;
49
50 @SuppressWarnings("serial")
51 class MemoryTab extends Tab implements ActionListener, ItemListener {
52 JComboBox plotterChoice;
53 TimeComboBox timeComboBox;
54 JButton gcButton;
55
56 PlotterPanel plotterPanel;
57 JPanel bottomPanel;
58 HTMLPane details;
59 PoolChart poolChart;
60
61 ArrayList<Plotter> plotterList;
62 Plotter heapPlotter, nonHeapPlotter;
63
64 private MemoryOverviewPanel overviewPanel;
65
66 private static final String usedKey = "used";
67 private static final String committedKey = "committed";
68 private static final String maxKey = "max";
69 private static final String thresholdKey = "threshold";
70
71 private static final String usedName = Resources.getText("Used");
72 private static final String committedName = Resources.getText("Committed");
73 private static final String maxName = Resources.getText("Max");
74 private static final String thresholdName = Resources.getText("Threshold");
75
76 private static final Color usedColor = Plotter.defaultColor;
77 private static final Color committedColor = null;
78 private static final Color maxColor = null;
79 private static final Color thresholdColor = Color.red;
80
81 private static final String infoLabelFormat = "MemoryTab.infoLabelFormat";
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107 public static String getTabName() {
108 return getText("Memory");
109 }
110
111 public MemoryTab(VMPanel vmPanel) {
112 super(vmPanel, getTabName());
113
114 setLayout(new BorderLayout(0, 0));
115 setBorder(new EmptyBorder(4, 4, 3, 4));
116
117 JPanel topPanel = new JPanel(new BorderLayout());
118 plotterPanel = new PlotterPanel(null);
119 bottomPanel = new JPanel(new BorderLayout());
120
121 add(topPanel, BorderLayout.NORTH);
122 add(plotterPanel, BorderLayout.CENTER);
123
124 JPanel controlPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 20, 5));
125 topPanel.add(controlPanel, BorderLayout.CENTER);
126
127
128 plotterChoice = new JComboBox();
129 plotterChoice.addItemListener(this);
130 controlPanel.add(new LabeledComponent(getText("Chart:"),
131 getMnemonicInt("Chart:"),
132 plotterChoice));
133
134
135 timeComboBox = new TimeComboBox();
136 controlPanel.add(new LabeledComponent(getText("Time Range:"),
137 getMnemonicInt("Time Range:"),
138 timeComboBox));
139
140 gcButton = new JButton(getText("Perform GC"));
141 gcButton.setMnemonic(getMnemonicInt("Perform GC"));
142 gcButton.addActionListener(this);
143 gcButton.setToolTipText(getText("Perform GC.toolTip"));
144 JPanel topRightPanel = new JPanel();
145 topRightPanel.setBorder(new EmptyBorder(0, 65-8, 0, 70));
146 topRightPanel.add(gcButton);
147 topPanel.add(topRightPanel, BorderLayout.AFTER_LINE_ENDS);
148
149 bottomPanel.setBorder(new CompoundBorder(new TitledBorder(getText("Details")),
150 new EmptyBorder(10, 10, 10, 10)));
151
152 details = new HTMLPane();
153 setAccessibleName(details, getText("Details"));
154 bottomPanel.add(new JScrollPane(details), BorderLayout.CENTER);
155
156 poolChart = new PoolChart();
157 bottomPanel.add(poolChart, BorderLayout.AFTER_LINE_ENDS);
158 }
159
160
161 private void createPlotters() throws IOException {
162 plotterList = new ArrayList<Plotter>();
163
164 ProxyClient proxyClient = vmPanel.getProxyClient();
165
166 heapPlotter = new Plotter(Plotter.Unit.BYTES) {
167 public String toString() {
168 return Resources.getText("Heap Memory Usage");
169 }
170 };
171 proxyClient.addWeakPropertyChangeListener(heapPlotter);
172
173 nonHeapPlotter = new Plotter(Plotter.Unit.BYTES) {
174 public String toString() {
175 return Resources.getText("Non-Heap Memory Usage");
176 }
177 };
178
179 setAccessibleName(heapPlotter,
180 getText("MemoryTab.heapPlotter.accessibleName"));
181 setAccessibleName(nonHeapPlotter,
182 getText("MemoryTab.nonHeapPlotter.accessibleName"));
183
184 proxyClient.addWeakPropertyChangeListener(nonHeapPlotter);
185
186 heapPlotter.createSequence(usedKey, usedName, usedColor, true);
187 heapPlotter.createSequence(committedKey, committedName, committedColor, false);
188 heapPlotter.createSequence(maxKey, maxName, maxColor, false);
189
190 nonHeapPlotter.createSequence(usedKey, usedName, usedColor, true);
191 nonHeapPlotter.createSequence(committedKey, committedName, committedColor, false);
192 nonHeapPlotter.createSequence(maxKey, maxName, maxColor, false);
193
194 plotterList.add(heapPlotter);
195 plotterList.add(nonHeapPlotter);
196
197
198 Map<ObjectName, MBeanInfo> mBeanMap = proxyClient.getMBeans("java.lang");
199 Set<ObjectName> keys = mBeanMap.keySet();
200 ObjectName[] objectNames = keys.toArray(new ObjectName[keys.size()]);
201 ArrayList<PoolPlotter> nonHeapPlotters = new ArrayList<PoolPlotter>(2);
202 for (ObjectName objectName : objectNames) {
203 String type = objectName.getKeyProperty("type");
204 if (type.equals("MemoryPool")) {
205 String name = getText("MemoryPoolLabel",
206 objectName.getKeyProperty("name"));
207
208 boolean isHeap = false;
209 AttributeList al =
210 proxyClient.getAttributes(objectName,
211 new String[] { "Type" });
212 if (al.size() > 0) {
213 isHeap = MemoryType.HEAP.name().equals(((Attribute)al.get(0)).getValue());
214 }
215 PoolPlotter poolPlotter = new PoolPlotter(objectName, name, isHeap);
216 proxyClient.addWeakPropertyChangeListener(poolPlotter);
217
218 poolPlotter.createSequence(usedKey, usedName, usedColor, true);
219 poolPlotter.createSequence(committedKey, committedName, committedColor, false);
220 poolPlotter.createSequence(maxKey, maxName, maxColor, false);
221 poolPlotter.createSequence(thresholdKey, thresholdName, thresholdColor, false);
222 poolPlotter.setUseDashedTransitions(thresholdKey, true);
223
224 if (isHeap) {
225 plotterList.add(poolPlotter);
226 } else {
227
228 nonHeapPlotters.add(poolPlotter);
229 }
230 }
231 }
232
233 for (PoolPlotter poolPlotter : nonHeapPlotters) {
234 plotterList.add(poolPlotter);
235 }
236 }
237
238
239 public void itemStateChanged(ItemEvent ev) {
240 if (ev.getStateChange() == ItemEvent.SELECTED) {
241 Plotter plotter = (Plotter)plotterChoice.getSelectedItem();
242 plotterPanel.setPlotter(plotter);
243 }
244 }
245
246 public void gc() {
247 new Thread("MemoryPanel.gc") {
248 public void run() {
249 ProxyClient proxyClient = vmPanel.getProxyClient();
250 try {
251 proxyClient.getMemoryMXBean().gc();
252 } catch (UndeclaredThrowableException e) {
253 proxyClient.markAsDead();
254 } catch (IOException e) {
255
256 }
257 }
258 }.start();
259 }
260
261 public SwingWorker<?, ?> newSwingWorker() {
262 return new SwingWorker<Boolean, Object>() {
263 private long[] used, committed, max, threshold;
264 private long timeStamp;
265 private String detailsStr;
266 private boolean initialRun = false;
267
268 public Boolean doInBackground() {
269 ProxyClient proxyClient = vmPanel.getProxyClient();
270
271 if (plotterList == null) {
272 try {
273 createPlotters();
274 } catch (UndeclaredThrowableException e) {
275 proxyClient.markAsDead();
276 return false;
277 } catch (final IOException ex) {
278 return false;
279 }
280 initialRun = true;
281 }
282
283 int n = plotterList.size();
284 used = new long[n];
285 committed = new long[n];
286 max = new long[n];
287 threshold = new long[n];
288 timeStamp = System.currentTimeMillis();
289 int poolCount = 0;
290
291 for (int i = 0; i < n; i++) {
292 Plotter plotter = plotterList.get(i);
293 MemoryUsage mu = null;
294 used[i] = -1L;
295 threshold[i] = -1L;
296
297 try {
298 if (plotter instanceof PoolPlotter) {
299 PoolPlotter poolPlotter = (PoolPlotter)plotter;
300 ObjectName objectName = poolPlotter.objectName;
301 AttributeList al =
302 proxyClient.getAttributes(objectName,
303 new String[] { "Usage", "UsageThreshold" });
304 if (al.size() > 0) {
305 CompositeData cd = (CompositeData)((Attribute)al.get(0)).getValue();
306 mu = MemoryUsage.from(cd);
307
308 if (al.size() > 1) {
309 threshold[i] = (Long)((Attribute)al.get(1)).getValue();
310 }
311 }
312 } else if (plotter == heapPlotter) {
313 mu = proxyClient.getMemoryMXBean().getHeapMemoryUsage();
314 } else if (plotter == nonHeapPlotter) {
315 mu = proxyClient.getMemoryMXBean().getNonHeapMemoryUsage();
316 }
317 } catch (UndeclaredThrowableException e) {
318 proxyClient.markAsDead();
319 return false;
320 } catch (IOException ex) {
321
322 }
323
324 if (mu != null) {
325 used[i] = mu.getUsed();
326 committed[i] = mu.getCommitted();
327 max[i] = mu.getMax();
328 }
329 }
330 detailsStr = formatDetails();
331
332 return true;
333 }
334
335 protected void done() {
336 try {
337 if (!get()) {
338 return;
339 }
340 } catch (InterruptedException ex) {
341 return;
342 } catch (ExecutionException ex) {
343 if (JConsole.isDebug()) {
344 ex.printStackTrace();
345 }
346 return;
347 }
348
349 if (initialRun) {
350
351 for (Plotter p : plotterList) {
352 plotterChoice.addItem(p);
353 timeComboBox.addPlotter(p);
354 }
355 add(bottomPanel, BorderLayout.SOUTH);
356 }
357
358
359 int n = plotterList.size();
360 int poolCount = 0;
361
362 for (int i = 0; i < n; i++) {
363 Plotter plotter = plotterList.get(i);
364 if (used[i] >= 0L) {
365 if (plotter instanceof PoolPlotter) {
366 plotter.addValues(timeStamp, used[i], committed[i], max[i], threshold[i]);
367 if (threshold[i] > 0L) {
368 plotter.setIsPlotted(thresholdKey, true);
369 }
370 poolChart.setValue(poolCount++, (PoolPlotter)plotter,
371 used[i], threshold[i], max[i]);
372 } else {
373 plotter.addValues(timeStamp, used[i], committed[i], max[i]);
374 }
375
376 if (plotter == heapPlotter && overviewPanel != null) {
377 overviewPanel.getPlotter().addValues(timeStamp, used[i]);
378 overviewPanel.updateMemoryInfo(used[i], committed[i], max[i]);
379 }
380 }
381 }
382 details.setText(detailsStr);
383 }
384 };
385 }
386
387 private String formatDetails() {
388 ProxyClient proxyClient = vmPanel.getProxyClient();
389 if (proxyClient.isDead()) {
390 return "";
391 }
392
393 String text = "<table cellspacing=0 cellpadding=0>";
394
395 Plotter plotter = (Plotter)plotterChoice.getSelectedItem();
396 if (plotter == null) {
397 return "";
398 }
399
400
401 long time = System.currentTimeMillis();
402 String timeStamp = formatDateTime(time);
403 text += newRow(getText("Time"), timeStamp);
404
405 long used = plotter.getLastValue(usedKey);
406 long committed = plotter.getLastValue(committedKey);
407 long max = plotter.getLastValue(maxKey);
408 long threshold = plotter.getLastValue(thresholdKey);
409
410 text += newRow(getText("Used"), formatKBytes(used));
411 if (committed > 0L) {
412 text += newRow(getText("Committed"), formatKBytes(committed));
413 }
414 if (max > 0L) {
415 text += newRow(getText("Max"), formatKBytes(max));
416 }
417 if (threshold > 0L) {
418 text += newRow(getText("Usage Threshold"), formatKBytes(threshold));
419 }
420
421 try {
422 Collection<GarbageCollectorMXBean> garbageCollectors =
423 proxyClient.getGarbageCollectorMXBeans();
424
425 boolean descPrinted = false;
426 for (GarbageCollectorMXBean garbageCollectorMBean : garbageCollectors) {
427 String gcName = garbageCollectorMBean.getName();
428 long gcCount = garbageCollectorMBean.getCollectionCount();
429 long gcTime = garbageCollectorMBean.getCollectionTime();
430 String str = getText("GC time details", justify(formatTime(gcTime), 14),
431 gcName,
432 String.format("%,d",gcCount));
433 if (!descPrinted) {
434 text += newRow(getText("GC time"), str);
435 descPrinted = true;
436 } else {
437 text += newRow(null, str);
438 }
439 }
440 } catch (IOException e) {
441 }
442
443 return text;
444 }
445
446 public void actionPerformed(ActionEvent ev) {
447 Object src = ev.getSource();
448 if (src == gcButton) {
449 gc();
450 }
451 }
452
453 private class PoolPlotter extends Plotter {
454 ObjectName objectName;
455 String name;
456 boolean isHeap;
457 long value, threshold, max;
458 int barX;
459
460 public PoolPlotter(ObjectName objectName, String name, boolean isHeap) {
461 super(Plotter.Unit.BYTES);
462
463 this.objectName = objectName;
464 this.name = name;
465 this.isHeap = isHeap;
466
467 setAccessibleName(this,
468 getText("MemoryTab.poolPlotter.accessibleName",
469 name));
470 }
471
472
473 public String toString() {
474 return name;
475 }
476 }
477
478 private class PoolChart extends BorderedComponent
479 implements Accessible, MouseListener {
480 final int height = 150;
481 final int leftMargin = 50;
482 final int rightMargin = 23;
483 final int bottomMargin = 35;
484 final int barWidth = 22;
485 final int barGap = 3;
486 final int groupGap = 8;
487 final int barHeight = height * 2 / 3;
488
489 final Color greenBar = new Color(100, 255, 100);
490 final Color greenBarBackground = new Color(210, 255, 210);
491 final Color redBarBackground = new Color(255, 210, 210);
492
493 Font smallFont = null;
494
495 ArrayList<PoolPlotter> poolPlotters = new ArrayList<PoolPlotter>(5);
496
497 int nHeapPools = 0;
498 int nNonHeapPools = 0;
499 Rectangle heapRect = new Rectangle(leftMargin, height - bottomMargin + 6, barWidth, 20);
500 Rectangle nonHeapRect = new Rectangle(leftMargin + groupGap, height - bottomMargin + 6, barWidth, 20);
501
502 public PoolChart() {
503 super(null, null);
504
505 setFocusable(true);
506 addMouseListener(this);
507 ToolTipManager.sharedInstance().registerComponent(this);
508 }
509
510 public void setValue(int poolIndex, PoolPlotter poolPlotter,
511 long value, long threshold, long max) {
512 poolPlotter.value = value;
513 poolPlotter.threshold = threshold;
514 poolPlotter.max = max;
515
516 if (poolIndex == poolPlotters.size()) {
517 poolPlotters.add(poolPlotter);
518 if (poolPlotter.isHeap) {
519 poolPlotter.barX = nHeapPools * (barWidth + barGap);
520 nHeapPools++;
521 heapRect.width = nHeapPools * barWidth + (nHeapPools - 1) * barGap;
522 nonHeapRect.x = leftMargin + heapRect.width + groupGap;
523 } else {
524 poolPlotter.barX = nonHeapRect.x - leftMargin + nNonHeapPools * (barWidth + barGap);
525 nNonHeapPools++;
526 nonHeapRect.width = nNonHeapPools * barWidth + (nNonHeapPools - 1) * barGap;
527 }
528 } else {
529 poolPlotters.set(poolIndex, poolPlotter);
530 }
531 repaint();
532 }
533
534 private void paintPoolBar(Graphics g, PoolPlotter poolPlotter) {
535 Rectangle barRect = getBarRect(poolPlotter);
536 g.setColor(Color.gray);
537 g.drawRect(barRect.x, barRect.y, barRect.width, barRect.height);
538
539 long value = poolPlotter.value;
540 long max = poolPlotter.max;
541 if (max > 0L) {
542 g.translate(barRect.x, barRect.y);
543
544
545 g.setColor(greenBarBackground);
546 g.fillRect(1, 1, barRect.width - 1, barRect.height - 1);
547
548 int greenHeight = (int)(value * barRect.height / max);
549 long threshold = poolPlotter.threshold;
550 if (threshold > 0L) {
551 int redHeight = (int)(threshold * barRect.height / max);
552
553
554 g.setColor(redBarBackground);
555 g.fillRect(1, 1, barRect.width - 1, barRect.height - redHeight);
556
557 if (value > threshold) {
558
559 g.setColor(thresholdColor);
560 g.fillRect(1, barRect.height - greenHeight,
561 barRect.width - 1, greenHeight - redHeight);
562 greenHeight = redHeight;
563 }
564 }
565
566
567 g.setColor(greenBar);
568 g.fillRect(1, barRect.height - greenHeight,
569 barRect.width - 1, greenHeight);
570
571 g.translate(-barRect.x, -barRect.y);
572 }
573 }
574
575 public void paintComponent(Graphics g) {
576 super.paintComponent(g);
577
578 if (poolPlotters.size() == 0) {
579 return;
580 }
581
582 if (smallFont == null) {
583 smallFont = g.getFont().deriveFont(9.0F);
584 }
585
586
587 g.setColor(getBackground());
588 Rectangle r = g.getClipBounds();
589 g.fillRect(r.x, r.y, r.width, r.height);
590
591 g.setFont(smallFont);
592 FontMetrics fm = g.getFontMetrics();
593 int fontDescent = fm.getDescent();
594
595
596 g.setColor(getForeground());
597 for (int pc : new int[] { 0, 25, 50, 75, 100 }) {
598 String str = pc + "% --";
599 g.drawString(str,
600 leftMargin - fm.stringWidth(str) - 4,
601 height - bottomMargin - (pc * barHeight / 100) + fontDescent + 1);
602 }
603
604 for (PoolPlotter poolPlotter : poolPlotters) {
605 paintPoolBar(g, poolPlotter);
606 }
607
608 g.setColor(Color.gray);
609 g.drawRect(heapRect.x, heapRect.y, heapRect.width, heapRect.height);
610 g.drawRect(nonHeapRect.x, nonHeapRect.y, nonHeapRect.width, nonHeapRect.height);
611
612 Color heapColor = greenBar;
613 Color nonHeapColor = greenBar;
614
615
616 for (PoolPlotter poolPlotter : poolPlotters) {
617 if (poolPlotter.threshold > 0L && poolPlotter.value > poolPlotter.threshold) {
618 if (poolPlotter.isHeap) {
619 heapColor = thresholdColor;
620 } else {
621 nonHeapColor = thresholdColor;
622 }
623 }
624 }
625 g.setColor(heapColor);
626 g.fillRect(heapRect.x + 1, heapRect.y + 1, heapRect.width - 1, heapRect.height - 1);
627 g.setColor(nonHeapColor);
628 g.fillRect(nonHeapRect.x + 1, nonHeapRect.y + 1, nonHeapRect.width - 1, nonHeapRect.height - 1);
629
630 String str = getText("Heap");
631 int stringWidth = fm.stringWidth(str);
632 int x = heapRect.x + (heapRect.width - stringWidth) / 2;
633 int y = heapRect.y + heapRect.height - 6;
634 g.setColor(Color.white);
635 g.drawString(str, x-1, y-1);
636 g.drawString(str, x+1, y-1);
637 g.drawString(str, x-1, y+1);
638 g.drawString(str, x+1, y+1);
639 g.setColor(Color.black);
640 g.drawString(str, x, y);
641
642 str = getText("Non-Heap");
643 stringWidth = fm.stringWidth(str);
644 x = nonHeapRect.x + (nonHeapRect.width - stringWidth) / 2;
645 y = nonHeapRect.y + nonHeapRect.height - 6;
646 g.setColor(Color.white);
647 g.drawString(str, x-1, y-1);
648 g.drawString(str, x+1, y-1);
649 g.drawString(str, x-1, y+1);
650 g.drawString(str, x+1, y+1);
651 g.setColor(Color.black);
652 g.drawString(str, x, y);
653
654
655 g.setColor(Color.blue);
656 r = null;
657 Plotter plotter = (Plotter)plotterChoice.getSelectedItem();
658 if (plotter == heapPlotter) {
659 r = heapRect;
660 } else if (plotter == nonHeapPlotter) {
661 r = nonHeapRect;
662 } else if (plotter instanceof PoolPlotter) {
663 r = getBarRect((PoolPlotter)plotter);
664 }
665 if (r != null) {
666 g.drawRect(r.x - 1, r.y - 1, r.width + 2, r.height + 2);
667 }
668 }
669
670 private Rectangle getBarRect(PoolPlotter poolPlotter) {
671 return new Rectangle(leftMargin + poolPlotter.barX,
672 height - bottomMargin - barHeight,
673 barWidth, barHeight);
674 }
675
676 public Dimension getPreferredSize() {
677 return new Dimension(nonHeapRect.x + nonHeapRect.width + rightMargin,
678 height);
679 }
680
681 public void mouseClicked(MouseEvent e) {
682 requestFocusInWindow();
683 Plotter plotter = getPlotter(e);
684
685 if (plotter != null && plotter != plotterChoice.getSelectedItem()) {
686 plotterChoice.setSelectedItem(plotter);
687 repaint();
688 }
689 }
690
691 public String getToolTipText(MouseEvent e) {
692 Plotter plotter = getPlotter(e);
693
694 return (plotter != null) ? plotter.toString() : null;
695 }
696
697 private Plotter getPlotter(MouseEvent e) {
698 Point p = e.getPoint();
699 Plotter plotter = null;
700
701 if (heapRect.contains(p)) {
702 plotter = heapPlotter;
703 } else if (nonHeapRect.contains(p)) {
704 plotter = nonHeapPlotter;
705 } else {
706 for (PoolPlotter poolPlotter : poolPlotters) {
707 if (getBarRect(poolPlotter).contains(p)) {
708 plotter = poolPlotter;
709 break;
710 }
711 }
712 }
713 return plotter;
714 }
715
716 public void mousePressed(MouseEvent e) {}
717 public void mouseReleased(MouseEvent e) {}
718 public void mouseEntered(MouseEvent e) {}
719 public void mouseExited(MouseEvent e) {}
720
721
722 public AccessibleContext getAccessibleContext() {
723 if (accessibleContext == null) {
724 accessibleContext = new AccessiblePoolChart();
725 }
726 return accessibleContext;
727 }
728
729 protected class AccessiblePoolChart extends AccessibleJPanel {
730 public String getAccessibleName() {
731 String name = getText("MemoryTab.poolChart.accessibleName");
732
733 String keyValueList = "";
734 for (PoolPlotter poolPlotter : poolPlotters) {
735 String value = (poolPlotter.value * 100 / poolPlotter.max) + "%";
736
737 keyValueList +=
738 getText("Plotter.accessibleName.keyAndValue",
739 poolPlotter.toString(), value);
740 if (poolPlotter.threshold > 0L) {
741 String threshold =
742 (poolPlotter.threshold * 100 / poolPlotter.max) + "%";
743 if (poolPlotter.value > poolPlotter.threshold) {
744 keyValueList +=
745 getText("MemoryTab.poolChart.aboveThreshold",
746 threshold);
747 } else {
748 keyValueList +=
749 getText("MemoryTab.poolChart.belowThreshold",
750 threshold);
751 }
752 }
753 }
754
755 return name + "\n" + keyValueList + ".";
756 }
757 }
758 }
759
760
761 OverviewPanel[] getOverviewPanels() {
762 if (overviewPanel == null) {
763 overviewPanel = new MemoryOverviewPanel();
764 }
765 return new OverviewPanel[] { overviewPanel };
766 }
767
768 private static class MemoryOverviewPanel extends OverviewPanel {
769 MemoryOverviewPanel() {
770 super(getText("Heap Memory Usage"), usedKey, usedName, Plotter.Unit.BYTES);
771 }
772
773 private void updateMemoryInfo(long used, long committed, long max) {
774 getInfoLabel().setText(getText(infoLabelFormat,
775 formatBytes(used, true),
776 formatBytes(committed, true),
777 formatBytes(max, true)));
778 }
779 }
780 }